//package com.bsj.power.pls.queue;
//
//import com.alibaba.fastjson.JSON;
//import com.bsj.consumerQ.function.HandleRunT;
//import com.bsj.consumerQ.method.QueueAndRunT;
//import com.bsj.power.common.config.cached.*;
//import com.bsj.power.common.config.redis.AlarmConstant;
//import com.bsj.power.common.config.redis.RedisConstant;
//import com.bsj.power.common.config.rocketmq.producer.BaseMqPushUtil;
//import com.bsj.power.common.constant.MqTopicAndTagConstants;
//import com.bsj.power.common.constant.NumericalConstants;
//import com.bsj.power.common.def.dto.cardReport.BindCardDTO;
//import com.bsj.power.common.def.entity.alarmReport.AlarmReport;
//import com.bsj.power.common.def.entity.job.WorkPersonnel;
//import com.bsj.power.common.def.entity.locationDevice.LocationDevice;
//import com.bsj.power.common.def.entity.path.Path;
//import com.bsj.power.common.def.entity.path.PathPoint;
//import com.bsj.power.common.def.entity.personnel.Personnel;
//import com.bsj.power.common.def.handleData.path.MidPathAlarmState;
//import com.bsj.power.common.def.vo.WebSocketMsgVO;
//import com.bsj.power.common.def.vo.pls.httpVo.HttpTagPosVO;
//import com.bsj.power.common.mapper.AlarmReportMapper;
//import com.bsj.power.common.util.DateUtils;
//import com.bsj.power.common.util.ExceptionUtil;
//import com.bsj.power.common.util.FindMediaDevUtils;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.collections4.CollectionUtils;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//
//import javax.annotation.Resource;
//import java.sql.Time;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Date;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * @author yinhao
// * @version 1.0
// * @description 进出围栏报警
// * @date 2024/8/18
// */
//@Slf4j
//@Component
//public class PathAlarmHandle extends QueueAndRunT<HttpTagPosVO> {
//
//    @Autowired
//    private PathCached pathCached;
//
//    @Autowired
//    private RedisCached redisCached;
//
//    @Autowired
//    private BindCardCached bindCardCached;
//
//    @Autowired
//    private LocationDeviceCached locationDeviceCached;
//
//    @Autowired
//    private PersonnelCached personnelCached;
//
//    @Autowired
//    private WorkPersonnelCached workPersonnelCached;
//
//    @Autowired
//    private PathAlarmCached pathAlarmCached;
//
//    @Autowired
//    private BaseMqPushUtil baseMqPushUtil;
//
//    @Resource
//    private AlarmReportMapper alarmReportMapper;
//
//
//    public void start() {
//        start("PathAlarmHandleQueue", new HandleRunT<HttpTagPosVO>() {
//
//            @Override
//            public void doRun(List<HttpTagPosVO> list) {
//                if (CollectionUtils.isEmpty(list)) {
//                    return;
//                }
//                //获取全部围栏信息
//                try {
//                    List<Path> paths = pathCached.hgetAllPathInfo();
//                    for (HttpTagPosVO httpTagPosVO : list) {
//                        //位置点信息，Y为高度,先当做平面，只计算X,Z的范围
//                        double[] pos = httpTagPosVO.getPos();
//                        //aX, aY, aZ是根据地图三维模型来做判别,存储还是不变
//                        double aX = pos[0];
//                        //人员位置跟3D模型的不一致,人员位置的y应换成第三位
//                        double aY = pos[2];
//                        //取反值
//                        double aZ = -pos[1];
//                        //真实的人员位置
//                        double x = pos[0];
//                        double y = pos[1];
//                        double z = pos[2];
//                        //定位时间
//                        long time = httpTagPosVO.getTime();
//                        Date date = new Date(time);
//                        //UWB设备号
//                        String sn = httpTagPosVO.getSn();
//                        LocationDevice locationDevice = locationDeviceCached.hgetLocationDeviceInfo(sn);
//                        if (locationDevice == null) {
//                            log.info("设备信息不存在: {}", sn);
//                            continue;
//                        }
//                        //绑卡信息
//                        BindCardDTO bindCardDTO = bindCardCached.hgetBindCardInfo(RedisConstant.BIND_CARD_REDIS_DEVICE_NAME_KEY + sn);
//                        if (bindCardDTO == null) {
//                            log.info("设备未绑卡不进行进出围栏报警处理{}", sn);
//                            continue;
//                        }
//                        //负责人员信息
//                        Personnel personnel = personnelCached.hgetPersonnelInfo(bindCardDTO.getEmpNo());
//                        //作业人员信息
//                        WorkPersonnel workPersonnel = workPersonnelCached.getWorkPersonnelInfo(bindCardDTO.getEmpNo());
//                        if (personnel == null && workPersonnel == null) {
//                            log.info("无效的人员信息,工号: {}", bindCardDTO.getEmpNo());
//                            continue;
//                        }
//                        Integer personnelId = null;
//                        String personnelName = null;
//                        if (workPersonnel != null) {
//                            personnelId = workPersonnel.getWorkPersonnelId();
//                            personnelName = workPersonnel.getName();
//                        } else {
//                            if (personnel != null) {
//                                personnelId = personnel.getPersonnelId();
//                                personnelName = personnel.getName();
//                            }
//                        }
//                        Integer deviceType = locationDevice.getDeviceType();
//                        String nikeName = locationDevice.getNikeName();
//                        List<AlarmReport> insertAlarmReport = new ArrayList<>();
//
//                        for (Path path : paths) {
//                            try {
//                                //围栏ID
//                                Integer pathId = path.getPathId();
//                                //围栏名称
//                                String pathName = path.getPathName();
//                                //围栏类型 1进围栏 2出围栏
//                                Integer pathStatus = path.getStatus();
//                                //首先判断时间
//                                boolean comparison = timeCompare(date, path.getBeginTime(), path.getEndTime());
//                                if (!comparison) {
//                                    log.info("时间不在范围里,围栏信息: {}, 围栏开始结束时间:{} - {},  设备数据时间：{}", pathName, path.getBeginTime(), path.getEndTime(), DateUtils.dateToStr(date));
//                                    continue;
//                                }
//                                //关联摄像头信息
//                                List<Long> cameraIds = pathCached.smemsPathDevice(pathId);
//                                //判断是否在该围栏内
//                                List<PathPoint> pathPoints = path.getPathPoints();
//                                List<String> xyAddList = pathPoints.stream().map(PathPoint::toAddString).collect(Collectors.toList());
//                                String areaCoordinates = xyAddList.stream().collect(Collectors.joining("|"));
//                                boolean inPoly = FindMediaDevUtils.IsPtInPoly(aX, aZ, areaCoordinates);
//                                log.info("围栏信息: {}, 对应的位置点信息: {}, 是否在区域内: {}", pathName, areaCoordinates, inPoly);
//                                //根据设备号跟围栏ID获取中间状态
//                                String midPathState = redisCached.hget(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "");
//                                //围栏报警中间状态
//                                MidPathAlarmState midPathAlarmState;
//                                if (midPathState == null) {
//                                    midPathAlarmState = MidPathAlarmState.builder()
//                                            .time(time).x(x).y(y).z(z).build();
//                                } else {
//                                    midPathAlarmState = JSON.parseObject(midPathState, MidPathAlarmState.class);
//                                }
//                                //报警对象
//                                // midState=0 即中间状态是正常的(第一次创建中间状态时默认正常) midState=1 中间状态不正常
//                                int midState = midPathAlarmState.getState();
//                                //1 禁止进入围栏，对应进围栏报警
//                                if (pathStatus.equals(NumericalConstants.ONE)) {
//                                    notEnterPath(midState, sn, pathId, pathName, pathStatus, inPoly,
//                                            personnelId, personnelName, nikeName, deviceType, time,
//                                            pos, redisCached, pathAlarmCached, midPathAlarmState,
//                                            cameraIds, insertAlarmReport, baseMqPushUtil);
//                                } else if (pathStatus.equals(NumericalConstants.TWO)) {
//                                    notDriveOutPath(midState, sn, pathId, pathName, pathStatus, inPoly,
//                                            personnelId, personnelName, nikeName, deviceType, time,
//                                            pos, redisCached, pathAlarmCached, midPathAlarmState,
//                                            cameraIds, insertAlarmReport, baseMqPushUtil);
//                                }
//                            } catch (Exception e) {
//                                log.info("围栏计算错误: {}, 异常信息: {}", path.toString(), ExceptionUtil.getStackStr(e));
//                                continue;
//                            }
//                        }
//                        try {
//                            if (!insertAlarmReport.isEmpty()) {
//                                //报表存储
//                                insertAlarmReport.stream().forEach(item -> {
//                                    alarmReportMapper.insert(item);
//                                });
//                            }
//                        } catch (Exception e) {
//                            log.info("进出围栏报警存储错误: {}, 异常信息: {}", ExceptionUtil.getStackStr(e));
//                            continue;
//                        }
//                    }
//                } catch (Exception e) {
//                    log.info("进出围栏计算错误: {}, 异常信息: {}", ExceptionUtil.getStackStr(e));
//                    return;
//                }
//            }
//        });
//    }
//
//    /**
//     * 禁止驶入围栏
//     *
//     * @param midState
//     * @param sn
//     * @param pathId
//     * @param pathName
//     * @param pathStatus
//     * @param inPoly
//     * @param personnelId
//     * @param personnelName
//     * @param nikeName
//     * @param deviceType
//     * @param time
//     * @param pos
//     * @param redisCached
//     * @param pathAlarmCached
//     * @param midPathAlarmState
//     * @param insertAlarmReport
//     */
//    private static void notEnterPath(int midState, String sn, Integer pathId, String pathName, Integer pathStatus,
//                                     boolean inPoly, Integer personnelId, String personnelName, String nikeName,
//                                     Integer deviceType, long time, double[] pos, RedisCached redisCached,
//                                     PathAlarmCached pathAlarmCached, MidPathAlarmState midPathAlarmState,
//                                     List<Long> cameraIds, List<AlarmReport> insertAlarmReport, BaseMqPushUtil baseMqPushUtil) {
//        double x = pos[0];
//        double y = pos[1];
//        double z = pos[2];
//        if (midState == 0) {
//            //中间状态正常，本次不在区域内，不需要处理直接返回
//            if (!inPoly) {
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//            } else {
//                //中间状态正常，本次在区域中，需要作报警处理
//                AlarmReport alarmReport = new AlarmReport(sn, personnelId, pathId,
//                        nikeName, deviceType, personnelName, pathName, pathStatus,
//                        time, Arrays.toString(pos), 1);
//                alarmReport.setCameraIds(cameraIds);
//                //缓存报警状态
//                pathAlarmCached.hsetPathAlarmInfo(alarmReport);
//                // 修改围栏报警中间状态
//                midPathAlarmState.setState(NumericalConstants.ONE);
//                midPathAlarmState.setTime(time);
//                midPathAlarmState.setX(x);
//                midPathAlarmState.setY(y);
//                midPathAlarmState.setZ(z);
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//
//                //报警信息推送
//                WebSocketMsgVO webSocketMsgVO = WebSocketMsgVO.builder()
//                        .msgType(NumericalConstants.TWO)
//                        .obj(alarmReport)
//                        .build();
//                baseMqPushUtil.sendTopicBytes(MqTopicAndTagConstants.SYSTEM_WEB_SERVER_CHANGE_TOPIC,
//                        MqTopicAndTagConstants.SYSTEM_WEB_PRODUCT_CHANGE_TAG, JSON.toJSONBytes(webSocketMsgVO));
//            }
//        } else if (midState == 1) {
//            //中间状态不正常, 本次不在区域里,需要结束报警并进行数据记录，并修改中间状态
//            if (!inPoly) {
//                AlarmReport alarmReport = new AlarmReport(sn, personnelId, pathId,
//                        nikeName, deviceType, personnelName, pathName, pathStatus,
//                        time, Arrays.toString(pos), 1);
//                alarmReport.setBeginTime(new Date(midPathAlarmState.getTime()));
//                alarmReport.setEndTime(new Date(time));
//                //开始与结束的位置点
//                alarmReport.setPos(Arrays.toString(new Double[]{midPathAlarmState.getX(), midPathAlarmState.getY(), midPathAlarmState.getZ()}));
//                alarmReport.setEndPos(Arrays.toString(pos));
//                insertAlarmReport.add(alarmReport);
//                //恢复中间位置状态
//                midPathAlarmState.setState(NumericalConstants.ZERO);
//                midPathAlarmState.setTime(time);
//                midPathAlarmState.setX(x);
//                midPathAlarmState.setY(y);
//                midPathAlarmState.setZ(z);
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//                //删除缓存中的报警数据
//                pathAlarmCached.hdelPathAlarmInfo(sn, pathId);
//            } else {
//                //中间状态不正常，本次在区域内，不做处理
//            }
//        }
//    }
//
//
//    /**
//     * 禁止驶出围栏
//     *
//     * @param midState
//     * @param sn
//     * @param pathId
//     * @param pathName
//     * @param pathStatus
//     * @param inPoly
//     * @param personnelId
//     * @param personnelName
//     * @param nikeName
//     * @param deviceType
//     * @param time
//     * @param pos
//     * @param redisCached
//     * @param pathAlarmCached
//     * @param midPathAlarmState
//     * @param insertAlarmReport
//     */
//    private static void notDriveOutPath(int midState, String sn, Integer pathId, String pathName, Integer pathStatus,
//                                        boolean inPoly, Integer personnelId, String personnelName, String nikeName,
//                                        Integer deviceType, long time, double[] pos, RedisCached redisCached,
//                                        PathAlarmCached pathAlarmCached, MidPathAlarmState midPathAlarmState, List<Long> cameraIds, List<AlarmReport> insertAlarmReport, BaseMqPushUtil baseMqPushUtil) {
//        double x = pos[0];
//        double y = pos[1];
//        double z = pos[2];
//        //禁止出围栏，对应出围栏报警
//        if (midState == 0) {
//            //中间状态正常
//            if (inPoly) {
//                //本次在围栏内，不需要处理
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//            } else {
//                //中间状态正常，本次不在围栏区域中，需要报警
//                AlarmReport alarmReport = new AlarmReport(sn, personnelId, pathId,
//                        nikeName, deviceType, personnelName, pathName, pathStatus,
//                        time, Arrays.toString(pos), 1);
//                alarmReport.setCameraIds(cameraIds);
//                //缓存报警状态
//                pathAlarmCached.hsetPathAlarmInfo(alarmReport);
//                // 修改围栏报警中间状态
//                midPathAlarmState.setState(NumericalConstants.ONE);
//                midPathAlarmState.setTime(time);
//                midPathAlarmState.setX(x);
//                midPathAlarmState.setY(y);
//                midPathAlarmState.setZ(z);
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//
//                //报警信息推送
//                WebSocketMsgVO webSocketMsgVO = WebSocketMsgVO.builder()
//                        .msgType(NumericalConstants.TWO)
//                        .obj(alarmReport)
//                        .build();
//                baseMqPushUtil.sendTopicBytes(MqTopicAndTagConstants.SYSTEM_WEB_SERVER_CHANGE_TOPIC,
//                        MqTopicAndTagConstants.SYSTEM_WEB_PRODUCT_CHANGE_TAG, JSON.toJSONBytes(webSocketMsgVO));
//            }
//        } else if (midState == 1) {
//            //中间状态不正常,在围栏区域内,需要结束报警并保存数据，并修改中间状态
//            if (inPoly) {
//                AlarmReport alarmReport = new AlarmReport(sn, personnelId, pathId,
//                        nikeName, deviceType, personnelName, pathName, pathStatus,
//                        time, Arrays.toString(pos), 1);
//                alarmReport.setBeginTime(new Date(midPathAlarmState.getTime()));
//                alarmReport.setEndTime(new Date(time));
//                //开始与结束的位置点
//                alarmReport.setPos(Arrays.toString(new Double[]{midPathAlarmState.getX(), midPathAlarmState.getY(), midPathAlarmState.getZ()}));
//                alarmReport.setEndPos(Arrays.toString(pos));
//                insertAlarmReport.add(alarmReport);
//                //恢复中间位置状态
//                midPathAlarmState.setState(NumericalConstants.ZERO);
//                midPathAlarmState.setTime(time);
//                midPathAlarmState.setX(x);
//                midPathAlarmState.setY(y);
//                midPathAlarmState.setZ(z);
//                redisCached.hset(AlarmConstant.MID_SAFETY_PATH_STATE + sn, pathId + "", JSON.toJSONString(midPathAlarmState));
//                //删除缓存中的报警数据
//                pathAlarmCached.hdelPathAlarmInfo(sn, pathId);
//            }
//        }
//    }
//
//    /**
//     * 时间比较
//     * 在两个时间范围内返回true
//     *
//     * @param date
//     * @param beginTime
//     * @param endTime
//     * @return boolean
//     * @author ljx
//     * @time 2024/5/21 19:23
//     */
//    private static boolean timeCompare(Date date, Time beginTime, Time endTime) {
//        Time time = Time.valueOf(DateUtils.dateToStr(DateUtils.TIME_STANDARD_FORMAT_HMS, date));
//        return time.compareTo(beginTime) >= NumericalConstants.ZERO && time.compareTo(endTime) <= NumericalConstants.ZERO;
//    }
//
//    public static void main(String[] args) {
//        String ar = "55.52123560466474,-16.033902657029458|55.52123560466474,-91.28063429997576|28.085424703301847,-91.28063429997576|28.085424703301847,-16.033902657029458";
//        boolean isPtInPoly = FindMediaDevUtils.IsPtInPoly(41.75527728290294D, -1.488270628364759, ar);
//        System.out.println(isPtInPoly);
//    }
//
//}
